﻿using Autofac;
using Common;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DBContext;
using EV.EventBus;
using FreeSql.Internal.Model;
using Manager.Common;
using Microsoft.Win32;
using NLog;
using NLog.Targets;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Data;
using ZoneLine.Models;
using ZoneLine.Models.PackageModel;
using ZoneLine.Models.QOPStation;
using ZoneLine.Views;
using static FreeSql.Internal.GlobalFilter;

namespace ZoneLine.ViewModels
{
    public class HistoryViewModel : ViewModelBase
    {
        private ILogger _logger;

        private IModelDAL _dal;

        public HistoryViewModel()
        {
            _dal = ContainerServer.Container.Resolve<IModelDAL>();
            _logger = ContainerServer.logger;

            StationLst = new List<string> { "OP620", "OP640", "OP550", "OP560", "OP570", "OP580", "OP590" };
        }

        private List<string> _stationLst;

        public List<string> StationLst
        {
            get { return _stationLst; }
            set => SetProperty(ref _stationLst, value);
        }

        private string _targetStation;

        public string TargetStation
        {
            get { return _targetStation; }
            set => SetProperty(ref _targetStation, value);
        }

        private string _code;

        public string Code
        {
            get { return _code; }
            set => SetProperty(ref _code, value);
        }

        private bool _timeQuery = true;

        public bool TimeQuery
        {
            get { return _timeQuery; }
            set => SetProperty(ref _timeQuery, value);
        }

        private bool _codeQuery;

        public bool CodeQuery
        {
            get { return _codeQuery; }
            set { SetProperty(ref _codeQuery, value); TargetStation = string.Empty; }
        }

        private bool _packageCodeQuery;

        /// <summary>
        /// 箱码查询
        /// </summary>
        public bool PackageCodeQuery
        {
            get { return _packageCodeQuery; }
            set => SetProperty(ref _packageCodeQuery, value);
        }

        private bool _packageCodeQueryRe;

        /// <summary>
        /// 通过工件码查箱码
        /// </summary>
        public bool PackageCodeQueryRe
        {
            get { return _packageCodeQueryRe; }
            set => SetProperty(ref _packageCodeQueryRe, value);
        }

        private bool _absCodeQuery;

        public bool AbsCodeQuery
        {
            get { return _absCodeQuery; }
            set => SetProperty(ref _absCodeQuery, value);
        }

        private bool _allRlt = true;

        /// <summary>
        /// 查询所有结论
        /// </summary>
        public bool AllRlt
        {
            get { return _allRlt; }
            set => SetProperty(ref _allRlt, value);
        }

        private bool _normalRlt;

        /// <summary>
        /// 只查询正常结论
        /// </summary>
        public bool NormalRlt
        {
            get { return _normalRlt; }
            set => SetProperty(ref _normalRlt, value);
        }

        private DateTime _startDate = DateTime.Now.AddDays(-1);

        public DateTime StartDate
        {
            get { return _startDate; }
            set => SetProperty(ref _startDate, value);
        }

        private DateTime _endDate = DateTime.Now;

        public DateTime EndDate
        {
            get { return _endDate; }
            set { _endDate = value; }
        }

        private DateTime _startTime = DateTime.Today.AddHours(0).AddMinutes(0).AddSeconds(0);//DateTime.Now;

        /// <summary>
        /// 开始时间
        /// </summary>
        public DateTime StartTime
        {
            get { return _startTime; }
            set => SetProperty(ref _startTime, value);
        }

        private DateTime _endTime = DateTime.Today.AddHours(23).AddMinutes(59).AddSeconds(59);// DateTime.Now;

        /// <summary>
        /// 结束时间
        /// </summary>
        public DateTime EndTime
        {
            get { return _endTime; }
            set => SetProperty(ref _endTime, value);
        }

        private List<string> _producerLst;

        public List<string> ProducerLst
        {
            get { return _producerLst; }
            set { _producerLst = value; }
        }

        /// <summary>
        /// 选中的生产厂商
        /// </summary>
        public string SelectedProducer { get; set; } = "全部";

        private List<object> _recordInfos;

        public List<object> RecordInfos
        {
            get { return _recordInfos; }
            set => SetProperty(ref _recordInfos, value);
        }

        private RelayCommand _queryDataCmd;

        public RelayCommand QueryDataCmd
        {
            get { return _queryDataCmd ?? (_queryDataCmd = new RelayCommand(async () => await QueryData())); }
        }

        private async Task QueryData()
        {
            var (isOk, startTime, endTime) = Tuple.Create(false, DateTime.Now, DateTime.Now);
            if (TimeQuery)
            {
                if (string.IsNullOrEmpty(TargetStation))
                {
                    ShowMsg("请选择工位");
                    return;
                }

                (isOk, startTime, endTime) = CheckCondition();
                if (!isOk)
                {
                    ShowMsg("请检查时间格式");
                    return;
                }
            }
            if (CodeQuery && string.IsNullOrEmpty(Code))
            {
                ShowMsg("请先输入条码");
                return;
            }

            await Task.Run(() =>
            {
                try
                {
                    RecordInfos = null;
                    if (TimeQuery)
                    {
                        LoadingModel.IsBusy = true;
                        List<object> temp = null;
                        switch (TargetStation)
                        {
                            case "OP620":
                                temp = QueryData<HOP010StationResult>(startTime, endTime);
                                break;

                            case "OP640":
                                temp = QueryData<HOP040StationResult>(startTime, endTime);
                                break;

                            case "OP550":
                                temp = QueryData<QOP006StationResult>(startTime, endTime);
                                break;

                            case "OP570":
                                temp = QueryData<QOP010StationResult>(startTime, endTime);
                                break;

                            case "OP560":
                                temp = QueryData<QOP020StationResult>(startTime, endTime);
                                break;

                            case "OP580":
                                temp = QueryData<QOP050LStationResult>(startTime, endTime);
                                break;

                            case "OP590":
                                temp = QueryData<QOP050RStationResult>(startTime, endTime);
                                break;

                            case "OP610":
                                temp = QueryData<QOP060StationResult>(startTime, endTime);
                                break;

                            default:
                                break;
                        }

                        RecordInfos = temp;
                    }
                    if (CodeQuery)
                    {
                        if (string.IsNullOrEmpty(Code))
                        {
                            return;
                        }
                        LoadingModel.IsBusy = true;

                        if (Cache.IsQopStaion == true)
                        {
                            var op006Result = _dal.GetModel<QOP006StationResult>(p => p.Code == Code);
                            var op010Result = _dal.GetModel<QOP010StationResult>(p => p.Code == Code);
                            var op020Result = _dal.GetModel<QOP020StationResult>(p => p.Code == Code);
                            var op050LResult = _dal.GetModel<QOP050LStationResult>(p => p.Code == Code);
                            var op050RResult = _dal.GetModel<QOP050RStationResult>(p => p.Code == Code);
                            if (!(op006Result == null && op010Result == null && op020Result == null && op050LResult == null && op050RResult == null))
                            {
                                var model = new HOpResultModel { Code = Code, CreateTime = op050LResult != null ? op050LResult.CreateTime : op050RResult != null ? op050RResult.CreateTime : DateTime.Now, Op06Result = op006Result?.Result, Op010Result = op010Result?.Result, Op020Result = op020Result?.Result, Op050LResult = op050LResult?.Result, Op050RResult = op050RResult?.Result };
                                RecordInfos = new List<object> { model };
                            }
                        }
                        else if (Cache.IsHopStaion == true)
                        {
                            var op010Result = _dal.GetModel<HOP010StationResult>(p => p.Code == Code);
                            var op040Result = _dal.GetModel<HOP040StationResult>(p => p.Code == Code);

                            if (!(op010Result == null && op040Result == null))
                            {
                                var model = new QOpResultModel { Code = Code, CreateTime = op010Result != null ? op010Result.CreateTime : op040Result != null ? op040Result.CreateTime : DateTime.Now, Op010Result = op010Result?.Result, Op040Result = op040Result?.Result, };
                                RecordInfos = new List<object> { model };
                            }
                        }

                        LoadingModel.IsBusy = false;
                    }
                    else if (PackageCodeQuery)
                    {
                        //查询打印码
                        var absPrintCodeRlts = _dal.GetModelList<PackageResult>(p => p.BoxCode == Code);
                        var models = new List<object>();
                        foreach (var item in absPrintCodeRlts)
                        {
                            models.Add(item);
                        }
                        RecordInfos = models;
                    }
                    else if (AbsCodeQuery)
                    {
                        if (string.IsNullOrEmpty(Code))
                        {
                            return;
                        }
                        LoadingModel.IsBusy = true;

                        if (Cache.IsQopStaion)
                        {
                            var op006Result = _dal.GetModel<QOP006StationResult>(p => p.AbsScanCode == Code);
                            var op010Result = _dal.GetModel<QOP010StationResult>(p => p.AbsScanCode == Code);
                            var op020Result = _dal.GetModel<QOP020StationResult>(p => p.AbsScanCode == Code);
                            var op050LResult = _dal.GetModel<QOP050LStationResult>(p => p.AbsScanCode == Code);
                            var op050RResult = _dal.GetModel<QOP050RStationResult>(p => p.AbsScanCode == Code);

                            if (op006Result != null || op010Result != null || op020Result != null || op050LResult != null || op050RResult != null)
                            {
                                var model = new HOpResultModel { Code = Code, CreateTime = op050LResult != null ? op050LResult.CreateTime : op050RResult != null ? op050RResult.CreateTime : DateTime.Now, Op06Result = op006Result?.Result, Op010Result = op010Result?.Result, Op020Result = op020Result?.Result, Op050LResult = op050LResult?.Result, Op050RResult = op050RResult?.Result };
                                RecordInfos = new List<object> { model };
                            }
                        }
                        else if (Cache.IsHopStaion)
                        {
                            var op010Result = _dal.GetModel<HOP010StationResult>(p => p.AbsScanCode == Code);
                            var op040Result = _dal.GetModel<HOP040StationResult>(p => p.AbsScanCode == Code);

                            if (op010Result != null || op040Result != null)
                            {
                                var model = new QOpResultModel { Code = Code, CreateTime = op010Result != null ? op010Result.CreateTime : op040Result != null ? op040Result.CreateTime : DateTime.Now, Op040Result = op040Result?.Result, Op010Result = op010Result?.Result, };
                                RecordInfos = new List<object> { model };
                            }
                        }

                        LoadingModel.IsBusy = false;
                    }
                    else if (PackageCodeQueryRe)
                    {
                        var packageTemp = _dal.GetModel<PackageResult>(p => p.Code == Code);
                        if (packageTemp != null)
                        {
                            //查询打印码
                            var absPrintCodeRlts = _dal.GetModelList<PackageResult>(p => p.BoxCode == packageTemp.BoxCode);
                            var models = new List<object>();
                            foreach (var item in absPrintCodeRlts)
                            {
                                models.Add(item);
                            }
                            RecordInfos = models;
                        }
                    }

                    LoadingModel.ActionSuccess = true;
                }
                catch (Exception ex)
                {
                    LoadingModel.ActionFailed = true;
                    ShowMsg($"查询数据失败{ex.Message}");
                }
            });
        }

        private List<object> QueryData<T>(DateTime startTime, DateTime endTime) where T : StationResultBase, new()
        {
            var temp = new List<object> { };
            var sql = $@"select a.*,b.BoxCode as BoxCodeView
                         from {typeof(T).Name} a
                         left join packageresult b on a.AbsScanCode = b.AbsCode
                         where (AbsScanCode !='' and AbsScanCode is not null) and CreateTime between '{startTime.ToString("yyyy-MM-dd HH:mm:ss")}' and '{endTime.ToString("yyyy-MM-dd HH:mm:ss")}';";
            var hOP010Result = _dal.ExceSqlToList<T>(sql);
            //var hOP010Result = _dal.GetModelList<T>(p => p.CreateTime < endTime && p.CreateTime > startTime);

            for (var i = 0; i < hOP010Result.Count; i++)
            {
                temp.Add(hOP010Result[i]);
            }
            return temp;
        }

        private List<object> QueryDataByScanCode<T>(string code) where T : StationResultBase, new()
        {
            var temp = new List<object> { };
            var hOP010Result = _dal.GetModelList<T>(p => p.AbsScanCode.Equals(code));

            for (var i = 0; i < hOP010Result.Count; i++)
            {
                temp.Add(hOP010Result[i]);
            }
            return temp;
        }

        private Tuple<bool, DateTime, DateTime> CheckCondition()
        {
            var startTime = new DateTime(StartDate.Year, StartDate.Month, StartDate.Day, StartTime.Hour, StartTime.Minute, StartTime.Second);
            var endTime = new DateTime(EndDate.Year, EndDate.Month, EndDate.Day, EndTime.Hour, EndTime.Minute, EndTime.Second);
            _logger.Info($"data query start time is {StartDate.Year}_{StartDate.Month}_{StartDate.Day}_{StartTime.Hour}_{StartTime.Minute}_{StartTime.Second}");
            _logger.Info($"data query start time is {EndDate.Year}_{EndDate.Month}_{EndDate.Day}_{EndTime.Hour}_{EndTime.Minute}_{EndTime.Second}");
            _logger.Info($"time result starttime is {StartTime}_{EndTime}");
            var success = true;
            if (endTime < startTime)
            {
                ShowMsg("结束时间不能小于开始时间，请检查");
                success = false;
            }
            return Tuple.Create(success, startTime, endTime);
        }

        private RelayCommand _openInfoCmd;

        public RelayCommand OpenInfoCmd
        {
            get { return _openInfoCmd ?? (_openInfoCmd = new RelayCommand(OpenInfo)); }
        }

        private void OpenInfo()
        {
            try
            {
                if (TimeQuery || CodeQuery || PackageCodeQuery)
                {
                    if (IsPropertyExist(TargetPiece, "Code"))
                    {
                        MessageCenter.PublishAsync("openinfoview", TargetPiece.Code);
                        return;
                    }
                }
                else
                {
                    MessageCenter.PublishAsync("openinfoviewAbs", TargetPiece.Code);
                }
            }
            catch (Exception ex)
            {
            }
        }

        public static bool IsPropertyExist(dynamic data, string propertyname)
        {
            if (data is ExpandoObject)
                return ((IDictionary<string, object>)data).ContainsKey(propertyname);

            return data.GetType().GetProperty(propertyname) != null;
        }

        public dynamic TargetPiece { get; set; }

        private RelayCommand _exportCmd;

        public RelayCommand ExportCmd
        {
            get { return _exportCmd ?? (_exportCmd = new RelayCommand(ExportData)); }
        }

        /// <summary>
        /// 导出数据
        /// </summary>
        private async void ExportData()
        {
            try
            {
                SaveFileDialog dia = new SaveFileDialog();
                dia.Filter = "*.xlsx|*.*";
                dia.DefaultExt = "xlsx";
                dia.AddExtension = true;
                var rlt = dia.ShowDialog();

                if (rlt.HasValue && rlt.Value)
                {
                    LoadingModel.IsBusy = true;
                    var path = dia.FileName;
                    //if (TimeQuery && string.IsNullOrEmpty(TargetStation))
                    if (TimeQuery)
                    {
                        var tempStationList = string.IsNullOrEmpty(TargetStation) ? StationLst.ToList() : StationLst.Where(o => o == TargetStation);
                        List<object> temp = null;
                        var (isOk, startTime, endTime) = Tuple.Create(false, DateTime.Now, DateTime.Now);

                        (isOk, startTime, endTime) = CheckCondition();
                        //foreach (var item in StationLst)
                        foreach (var item in tempStationList)
                        {
                            switch (item)
                            {
                                case "OP620":
                                    temp = QueryData<HOP010StationResult>(startTime, endTime);
                                    break;

                                case "OP640":
                                    temp = QueryData<HOP040StationResult>(startTime, endTime);
                                    break;

                                case "OP550":
                                    temp = QueryData<QOP006StationResult>(startTime, endTime);
                                    break;

                                case "OP570":
                                    temp = QueryData<QOP010StationResult>(startTime, endTime);
                                    break;

                                case "OP560":
                                    temp = QueryData<QOP020StationResult>(startTime, endTime);
                                    break;

                                case "OP580":
                                    temp = QueryData<QOP050LStationResult>(startTime, endTime);
                                    break;

                                case "OP590":
                                    temp = QueryData<QOP050RStationResult>(startTime, endTime);
                                    break;

                                case "OP610":
                                    temp = QueryData<QOP060StationResult>(startTime, endTime);
                                    break;
                            }
                            if (temp != null && temp.Count > 0)
                            {
                                await Task.Run(() =>
                                {
                                    NPOIService.ExportToExcel(path, temp, sheetName: item);
                                });
                            }
                        }
                    }
                    if (CodeQuery && !string.IsNullOrEmpty(Code))
                    {
                        List<object> temp = null;
                        foreach (var item in StationLst)
                        {
                            switch (item)
                            {
                                case "OP620":
                                    temp = QueryDataByScanCode<HOP010StationResult>(Code);
                                    break;

                                case "OP640":
                                    temp = QueryDataByScanCode<HOP040StationResult>(Code);
                                    break;

                                case "OP550":
                                    temp = QueryDataByScanCode<QOP006StationResult>(Code);
                                    break;

                                case "OP570":
                                    temp = QueryDataByScanCode<QOP010StationResult>(Code);
                                    break;

                                case "OP560":
                                    temp = QueryDataByScanCode<QOP020StationResult>(Code);
                                    break;

                                case "OP580":
                                    temp = QueryDataByScanCode<QOP050LStationResult>(Code);
                                    break;

                                case "OP590":
                                    temp = QueryDataByScanCode<QOP050RStationResult>(Code);
                                    break;

                                case "OP610":
                                    temp = QueryDataByScanCode<QOP060StationResult>(Code);
                                    break;
                            }
                            if (temp != null && temp.Count > 0)
                            {
                                await Task.Run(() =>
                                {
                                    NPOIService.ExportToExcel(path, temp, sheetName: item);
                                });
                            }
                        }
                        if (RecordInfos == null || RecordInfos.Count < 1)
                        {
                            ShowMsg("不存在要导出的数据，请查到数据后再导出");
                            return;
                        }
                        await Task.Run(() =>
                        {
                            NPOIService.ExportToExcel(path, RecordInfos);
                        });
                    }
                }
                LoadingModel.ActionSuccess = true;
            }
            catch (Exception ex)
            {
                LoadingModel.ActionFailed = true;
                _logger?.Error(ex, "导出输入异常");
            }
        }
    }
}